<template>
  <div class="flow-editor">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-section">
        <span class="toolbar-label">节点类型:</span>
        <el-button 
          v-for="nodeType in nodeTypes" 
          :key="nodeType.type"
          size="small" 
          :type="nodeType.color"
          @click="addNode(nodeType.type)"
          :icon="nodeType.icon"
        >
          {{ nodeType.label }}
        </el-button>
      </div>
      
      <div class="toolbar-section">
        <el-button size="small" @click="saveFlow" type="primary" :loading="saving">
          <el-icon><DocumentAdd /></el-icon>
          保存流程
        </el-button>
        <el-button size="small" @click="clearFlow" type="danger">
          <el-icon><Delete /></el-icon>
          清空画布
        </el-button>
        <el-button size="small" @click="toggleFullscreen" :type="isFullscreen ? 'warning' : 'info'">
          <el-icon><FullScreen v-if="!isFullscreen" /><Aim v-else /></el-icon>
          {{ isFullscreen ? '退出全屏' : '全屏模式' }}
        </el-button>
      </div>
    </div>

    <!-- 流程图画布 -->
    <div class="flow-container">
      <VueFlow
        v-model="elements"
        :class="{ dark }"
        class="vue-flow-basic-example"
        :default-viewport="{ zoom: 1 }"
        :min-zoom="0.2"
        :max-zoom="4"
        :snap-to-grid="true"
        :snap-grid="[15, 15]"
        :connection-line-type="'smoothstep'"
        :connection-mode="'loose'"
        @node-click="onNodeClick"
        @edge-click="onEdgeClick"
        @connect="onConnect"
        @nodes-change="onNodesChange"
        @edges-change="onEdgesChange"
      >
        <!-- 自定义节点 -->
        <template #node-start="nodeProps">
          <StartNode v-bind="nodeProps" @delete="handleNodeDelete" />
        </template>
        
        <template #node-end="nodeProps">
          <EndNode v-bind="nodeProps" @delete="handleNodeDelete" />
        </template>
        
        <template #node-api="nodeProps">
          <ApiNode v-bind="nodeProps" @delete="handleNodeDelete" />
        </template>
        
        <template #node-condition="nodeProps">
          <ConditionNode v-bind="nodeProps" @delete="handleNodeDelete" />
        </template>
        
        <template #node-loop="nodeProps">
          <LoopNode v-bind="nodeProps" @delete="handleNodeDelete" />
        </template>

        <!-- 背景 -->
        <Background pattern-color="#aaa" :gap="16" />
        
        <!-- 控制器 -->
        <Controls />
        
        <!-- 小地图 -->
        <MiniMap />
      </VueFlow>
    </div>

    <!-- 节点配置弹窗 -->
    <el-dialog
      v-model="nodeDialogVisible"
      :title="getNodeDialogTitle()"
      width="800px"
      :before-close="handleNodeDialogClose"
    >
      <component 
        :is="getNodeConfigComponent()" 
        v-if="selectedNode"
        :node-data="selectedNode"
        :interfaces="interfaces"
        @save="handleNodeSave"
        @cancel="handleNodeCancel"
        @delete="handleNodeDelete"
      />
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { VueFlow, useVueFlow } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import { DocumentAdd, Delete, VideoPlay, Setting, Refresh, QuestionFilled, FullScreen, Aim } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// 自定义节点组件
import StartNode from './flow-nodes/StartNode.vue'
import EndNode from './flow-nodes/EndNode.vue'
import ApiNode from './flow-nodes/ApiNode.vue'
import ConditionNode from './flow-nodes/ConditionNode.vue'
import LoopNode from './flow-nodes/LoopNode.vue'

// 节点配置组件
import BasicNodeConfig from './flow-configs/BasicNodeConfig.vue'
import ApiNodeConfig from './flow-configs/ApiNodeConfig.vue'
import ConditionNodeConfig from './flow-configs/ConditionNodeConfig.vue'
import LoopNodeConfig from './flow-configs/LoopNodeConfig.vue'

const props = defineProps({
  scenarioId: {
    type: Number,
    default: null
  },
  interfaces: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['save', 'load'])

// Vue Flow 实例
const { addNodes, addEdges, removeNodes, removeEdges, getNodes, getEdges } = useVueFlow()

// 响应式数据
const elements = ref([])
const dark = ref(false)
const saving = ref(false)
const nodeDialogVisible = ref(false)
const selectedNode = ref(null)
const isFullscreen = ref(false)

// 节点类型配置
const nodeTypes = [
  { type: 'start', label: '开始', color: 'success', icon: VideoPlay },
  { type: 'api', label: '接口调用', color: 'primary', icon: Setting },
  { type: 'condition', label: '条件判断', color: 'warning', icon: QuestionFilled },
  { type: 'loop', label: '循环', color: 'info', icon: Refresh },
  { type: 'end', label: '结束', color: 'danger', icon: Delete }
]

// 节点ID计数器
let nodeIdCounter = 1
let edgeIdCounter = 1

// 添加节点
const addNode = (type) => {
  const nodeId = `${type}_${nodeIdCounter++}`
  const position = getOptimalNodePosition()
  
  const newNode = {
    id: nodeId,
    type: type,
    position: position,
    data: {
      label: getDefaultNodeLabel(type),
      config: getDefaultNodeConfig(type)
    }
  }
  
  addNodes([newNode])
  ElMessage.success(`已添加${getNodeTypeLabel(type)}节点`)
}

// 获取最优节点位置
const getOptimalNodePosition = () => {
  const existingNodes = getNodes.value
  const containerWidth = 800  // 流程图容器宽度
  const containerHeight = 600 // 流程图容器高度
  const nodeWidth = 180       // 节点宽度
  const nodeHeight = 80       // 节点高度
  const margin = 50           // 节点间距
  
  // 如果没有现有节点，在中心创建
  if (existingNodes.length === 0) {
    return {
      x: (containerWidth - nodeWidth) / 2,
      y: (containerHeight - nodeHeight) / 2
    }
  }
  
  // 寻找合适的位置，避免重叠
  const maxAttempts = 20
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    let x, y
    
    if (attempt < 10) {
      // 前10次尝试：在现有节点附近放置
      const randomNode = existingNodes[Math.floor(Math.random() * existingNodes.length)]
      const offsetX = (Math.random() - 0.5) * 300 // -150 到 150
      const offsetY = (Math.random() - 0.5) * 200 // -100 到 100
      
      x = Math.max(margin, Math.min(containerWidth - nodeWidth - margin, 
          randomNode.position.x + offsetX))
      y = Math.max(margin, Math.min(containerHeight - nodeHeight - margin, 
          randomNode.position.y + offsetY))
    } else {
      // 后10次尝试：随机位置
      x = Math.random() * (containerWidth - nodeWidth - 2 * margin) + margin
      y = Math.random() * (containerHeight - nodeHeight - 2 * margin) + margin
    }
    
    // 检查是否与现有节点重叠
    const hasOverlap = existingNodes.some(node => {
      const dx = Math.abs(node.position.x - x)
      const dy = Math.abs(node.position.y - y)
      return dx < nodeWidth + margin && dy < nodeHeight + margin
    })
    
    if (!hasOverlap) {
      return { x, y }
    }
  }
  
  // 如果所有尝试都失败，使用网格布局
  const gridSize = Math.ceil(Math.sqrt(existingNodes.length + 1))
  const gridIndex = existingNodes.length
  const gridX = gridIndex % gridSize
  const gridY = Math.floor(gridIndex / gridSize)
  
  return {
    x: margin + gridX * (nodeWidth + margin),
    y: margin + gridY * (nodeHeight + margin)
  }
}

// 获取默认节点标签
const getDefaultNodeLabel = (type) => {
  const labels = {
    start: '开始',
    end: '结束',
    api: '接口调用',
    condition: '条件判断',
    loop: '循环'
  }
  return labels[type] || '未知节点'
}

// 获取默认节点配置
const getDefaultNodeConfig = (type) => {
  const configs = {
    start: {},
    end: {},
    api: {
      interfaceId: null,
      parameterOverrides: {},
      variableExtractions: {}
    },
    condition: {
      expression: '',
      operator: 'equals',
      value: ''
    },
    loop: {
      type: 'count',
      count: 1,
      condition: ''
    }
  }
  return configs[type] || {}
}

// 获取节点类型标签
const getNodeTypeLabel = (type) => {
  const node = nodeTypes.find(n => n.type === type)
  return node ? node.label : '未知'
}

// 节点点击事件
const onNodeClick = (event) => {
  selectedNode.value = event.node
  nodeDialogVisible.value = true
}

// 边点击事件
const onEdgeClick = (event) => {
  console.log('Edge clicked:', event.edge)
}

// 连接事件
const onConnect = (params) => {
  console.log('Connection event triggered:', params)
  const edgeId = `edge_${edgeIdCounter++}`
  const newEdge = {
    id: edgeId,
    ...params,
    type: 'default',
    data: {
      label: ''
    }
  }
  console.log('Creating edge:', newEdge)
  addEdges([newEdge])
  ElMessage.success('连接已创建')
}

// 节点变化事件
const onNodesChange = (changes) => {
  console.log('Nodes changed:', changes)
}

// 边变化事件
const onEdgesChange = (changes) => {
  console.log('Edges changed:', changes)
}

// 获取节点对话框标题
const getNodeDialogTitle = () => {
  if (!selectedNode.value) return ''
  return `配置${getNodeTypeLabel(selectedNode.value.type)}节点`
}

// 获取节点配置组件
const getNodeConfigComponent = () => {
  if (!selectedNode.value) return null
  
  const componentMap = {
    start: BasicNodeConfig,
    end: BasicNodeConfig,
    api: ApiNodeConfig,
    condition: ConditionNodeConfig,
    loop: LoopNodeConfig
  }
  
  return componentMap[selectedNode.value.type] || BasicNodeConfig
}

// 处理节点保存
const handleNodeSave = (config) => {
  if (selectedNode.value) {
    selectedNode.value.data.config = { ...config }
    selectedNode.value.data.label = config.name || selectedNode.value.data.label
  }
  nodeDialogVisible.value = false
  selectedNode.value = null
  ElMessage.success('节点配置已保存')
}

// 处理节点取消
const handleNodeCancel = () => {
  nodeDialogVisible.value = false
  selectedNode.value = null
}

// 处理节点删除
const handleNodeDelete = (nodeData) => {
  // 删除节点
  removeNodes([nodeData])
  
  // 删除与该节点相关的所有连接
  const nodeId = nodeData.id
  const edges = getEdges.value
  const edgesToRemove = edges.filter(edge => 
    edge.source === nodeId || edge.target === nodeId
  )
  if (edgesToRemove.length > 0) {
    removeEdges(edgesToRemove)
  }
  
  // 关闭弹窗
  nodeDialogVisible.value = false
  selectedNode.value = null
  
  ElMessage.success('节点已删除')
}

// 处理节点对话框关闭
const handleNodeDialogClose = () => {
  nodeDialogVisible.value = false
  selectedNode.value = null
}

// 保存流程
const saveFlow = async () => {
  if (!props.scenarioId) {
    ElMessage.warning('请先选择一个测试场景')
    return
  }
  
  saving.value = true
  try {
    const nodes = getNodes.value
    const edges = getEdges.value
    
    const flowData = {
      nodes: nodes.map(node => ({
        node_id: node.id,
        node_type: node.type,
        name: node.data.label,
        position_x: node.position.x,
        position_y: node.position.y,
        node_config: node.data.config,
        is_enabled: true,
        continue_on_failure: false,
        interface_id: node.data.config?.interfaceId || null
      })),
      connections: edges.map(edge => ({
        connection_id: edge.id,
        source_node_id: edge.source,
        target_node_id: edge.target,
        connection_type: edge.type || 'default',
        condition_config: edge.data || {},
        is_enabled: true
      }))
    }
    
    emit('save', flowData)
    ElMessage.success('流程图已保存')
  } catch (error) {
    console.error('保存流程图失败:', error)
    ElMessage.error('保存流程图失败')
  } finally {
    saving.value = false
  }
}

// 清空画布
const clearFlow = () => {
  elements.value = []
  removeNodes(getNodes.value)
  removeEdges(getEdges.value)
  ElMessage.success('画布已清空')
}

// 全屏切换
const toggleFullscreen = () => {
  const flowContainer = document.querySelector('.flow-editor')
  
  if (!isFullscreen.value) {
    // 进入全屏
    if (flowContainer.requestFullscreen) {
      flowContainer.requestFullscreen()
    } else if (flowContainer.webkitRequestFullscreen) {
      flowContainer.webkitRequestFullscreen()
    } else if (flowContainer.mozRequestFullScreen) {
      flowContainer.mozRequestFullScreen()
    } else if (flowContainer.msRequestFullscreen) {
      flowContainer.msRequestFullscreen()
    }
    isFullscreen.value = true
  } else {
    // 退出全屏
    if (document.exitFullscreen) {
      document.exitFullscreen()
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen()
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen()
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen()
    }
    isFullscreen.value = false
  }
}

// 加载流程图数据
const loadFlowData = (flowData) => {
  if (!flowData) return
  
  const { nodes = [], connections = [] } = flowData
  
  // 清空现有元素
  elements.value = []
  
  // 添加节点 - 支持后端返回的下划线格式和前端的驼峰格式
  const flowNodes = nodes.map(node => ({
    id: node.node_id || node.nodeId,
    type: node.node_type || node.nodeType,
    position: { 
      x: node.position_x || node.positionX || 0, 
      y: node.position_y || node.positionY || 0 
    },
    data: {
      label: node.name,
      config: node.node_config || node.nodeConfig || {}
    }
  }))
  
  // 添加连接 - 支持后端返回的下划线格式和前端的驼峰格式
  const flowEdges = connections.map(conn => ({
    id: conn.connection_id || conn.connectionId,
    source: conn.source_node_id || conn.sourceNodeId,
    target: conn.target_node_id || conn.targetNodeId,
    type: conn.connection_type || conn.connectionType || 'default',
    data: conn.condition_config || conn.conditionConfig || {}
  }))
  
  elements.value = [...flowNodes, ...flowEdges]
  
  // 更新计数器
  if (nodes.length > 0) {
    nodeIdCounter = Math.max(...nodes.map(n => parseInt((n.node_id || n.nodeId || '').split('_')[1]) || 0)) + 1
  }
  if (connections.length > 0) {
    edgeIdCounter = Math.max(...connections.map(c => parseInt((c.connection_id || c.connectionId || '').split('_')[1]) || 0)) + 1
  }
}

// 暴露方法给父组件
defineExpose({
  loadFlowData,
  saveFlow,
  clearFlow
})

// 全屏状态变化监听
const handleFullscreenChange = () => {
  const isCurrentlyFullscreen = !!(
    document.fullscreenElement ||
    document.webkitFullscreenElement ||
    document.mozFullScreenElement ||
    document.msFullscreenElement
  )
  isFullscreen.value = isCurrentlyFullscreen
}

onMounted(() => {
  // 初始化时可以加载默认流程
  nextTick(() => {
    emit('load')
  })
  
  // 添加全屏状态监听器
  document.addEventListener('fullscreenchange', handleFullscreenChange)
  document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
  document.addEventListener('mozfullscreenchange', handleFullscreenChange)
  document.addEventListener('MSFullscreenChange', handleFullscreenChange)
})

onUnmounted(() => {
  // 清理全屏状态监听器
  document.removeEventListener('fullscreenchange', handleFullscreenChange)
  document.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
  document.removeEventListener('mozfullscreenchange', handleFullscreenChange)
  document.removeEventListener('MSFullscreenChange', handleFullscreenChange)
})
</script>

<style scoped>
.flow-editor {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #f5f5f5;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: white;
  border-bottom: 1px solid #e0e0e0;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.toolbar-section {
  display: flex;
  align-items: center;
  gap: 8px;
}

.toolbar-label {
  font-size: 14px;
  font-weight: 500;
  color: #666;
  margin-right: 8px;
}

.flow-container {
  flex: 1;
  position: relative;
}

.vue-flow-basic-example {
  height: 100%;
}

/* Vue Flow 样式覆盖 */
:deep(.vue-flow__background) {
  background-color: #fafafa;
}

:deep(.vue-flow__controls) {
  bottom: 20px;
  left: 20px;
}

:deep(.vue-flow__minimap) {
  bottom: 20px;
  right: 20px;
}

/* 自定义节点样式 */
:deep(.vue-flow__node) {
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  border: 2px solid transparent;
  transition: all 0.2s ease;
}

:deep(.vue-flow__node:hover) {
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

:deep(.vue-flow__node.selected) {
  border-color: #409eff;
}

/* 边样式 */
:deep(.vue-flow__edge-path) {
  stroke: #b1b1b7;
  stroke-width: 2;
}

:deep(.vue-flow__edge.selected .vue-flow__edge-path) {
  stroke: #409eff;
  stroke-width: 3;
}

:deep(.vue-flow__connection-line) {
  stroke: #409eff;
  stroke-width: 2;
  stroke-dasharray: 5,5;
}

/* 全屏模式样式 */
.flow-editor:fullscreen {
  background: #f5f5f5;
  padding: 0;
  margin: 0;
}

.flow-editor:-webkit-full-screen {
  background: #f5f5f5;
  padding: 0;
  margin: 0;
}

.flow-editor:-moz-full-screen {
  background: #f5f5f5;
  padding: 0;
  margin: 0;
}

.flow-editor:-ms-fullscreen {
  background: #f5f5f5;
  padding: 0;
  margin: 0;
}
</style>